package com.example.administrator.testproject.flagTextview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import com.example.administrator.testproject.R;

import java.util.ArrayList;
import java.util.List;

import static android.graphics.Paint.ANTI_ALIAS_FLAG;

/**
 * Created by shengfh on 2018/1/8.
 */

public class FlagTextView extends View {
    private float textSize;
    private float flagTextSize;
    private int textColor;
    private int flagTextColor;
    private float flagPadding;//flag左右padding
    private float flagMargin;//flag间距
    private float textMarginLeft;
    private float textMarginRight;
    private float lineSpacing;
    private int maxLine;
    private Paint paint;
    private int rowNum = 1;
    private float leftTotalWidth;
    private float rightTotalWidth;
    private String contentString;
    private int index;
    private List<FlagBean> leftFlags;
    private List<FlagBean> rightFlags = new ArrayList<>();

    private static final int DRAWABLE_FLAG = 1;

    private static final int DRAWABLE_PICTURE = 2;
    private int drawableTotalWidth;

    public void setContentText(String contentString) {
        this.contentString = contentString;
        postInvalidate();
    }

    public void addFlagText(String flag, @DrawableRes int vectorDrawableId, int textColor, int gravity) {
        if (TextUtils.isEmpty(flag) || TextUtils.isEmpty(flag.trim())) return;
        FlagBean flagBean = new FlagBean();
        flagBean.setType(DRAWABLE_FLAG);
        flagBean.setTxt(flag.trim());
        flagBean.setGravity(Gravity.LEFT);
        flagBean.setRes(vectorDrawableId);
        flagBean.setTextColor(textColor);
        if (gravity == Gravity.LEFT) {
            leftFlags.add(flagBean);
        } else if (gravity == Gravity.RIGHT) {
            rightFlags.add(flagBean);
        }

    }


    public void addFlagDrawable(@DrawableRes int vectorDrawableId, int gravity) {
        FlagBean flagBean = new FlagBean();
        flagBean.setType(DRAWABLE_PICTURE);
        flagBean.setGravity(gravity);
        flagBean.setRes(vectorDrawableId);
        if (gravity == Gravity.LEFT) {
            leftFlags.add(flagBean);
        } else if (gravity == Gravity.RIGHT) {
            rightFlags.add(flagBean);
        }
//        postInvalidate();
    }

    public void addFlagEntity(FlagBean flagBean) {
        rightFlags.add(flagBean);
//        postInvalidate();
    }

    public void clear() {
        if (leftFlags != null) leftFlags.clear();
        if (rightFlags != null) rightFlags.clear();
    }

    public FlagTextView(Context context) {
        super(context);
    }

    public FlagTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(attrs);
    }

    public FlagTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(attrs);
    }

    private void initView(AttributeSet attrs) {
        leftFlags = new ArrayList<>();

        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.FlagTextView);
        textSize = typedArray.getDimension(R.styleable.FlagTextView_text_Size, 14);
        textColor = typedArray.getColor(R.styleable.FlagTextView_text_Color, getResources().getColor(R.color.gray_3));
        flagTextSize = typedArray.getDimension(R.styleable.FlagTextView_flag_textSize, 10);
        flagTextColor = typedArray.getColor(R.styleable.FlagTextView_flag_textColor, getResources().getColor(R.color.gray_3));
        flagPadding = typedArray.getDimension(R.styleable.FlagTextView_flag_padding, 5);
        flagMargin = typedArray.getDimension(R.styleable.FlagTextView_flag_margin, 5);
        textMarginLeft = typedArray.getDimension(R.styleable.FlagTextView_text_margin_left, 10);
        textMarginRight = typedArray.getDimension(R.styleable.FlagTextView_text_margin_right, 10);
        lineSpacing = typedArray.getDimension(R.styleable.FlagTextView_line_spacing, 5);
        maxLine = typedArray.getInt(R.styleable.FlagTextView_flag_max_line, 0);
        typedArray.recycle();
        paint = new Paint();
        paint.setFlags(ANTI_ALIAS_FLAG);


    }

    @Override
    protected void onDraw(Canvas canvas) {
//        Log.e("Tag", "onDraw");
        index = 0;
        rowNum = 1;
        leftTotalWidth = 0;
        drawableTotalWidth = 0;
//        paint.setColor(flagTextColor);
//        canvas.drawColor(Color.WHITE);
//        canvas.drawLine(getPaddingLeft(), textSize / 2 + getPaddingTop(), getWidth() - getPaddingLeft(),
//                textSize / 2 + getPaddingTop(), paint);

        drawFlag(canvas, paint, leftFlags);
//        计算尾部图片总宽度
        for (int i = 0; i < rightFlags.size(); i++) {
            Bitmap bitmap = getBitmap(DRAWABLE_PICTURE, rightFlags.get(i).getRes(), 0);
            rightFlags.get(i).setBitmap(bitmap);
            if (i == 0) {
                drawableTotalWidth += bitmap.getWidth();
            } else if (i == rightFlags.size() - 1) {
                drawableTotalWidth += bitmap.getWidth();
            } else {
                drawableTotalWidth += bitmap.getWidth() + flagMargin;
            }
        }

        //画text
        paint.setTextSize(textSize);
        paint.setColor(textColor);
        paint.setTypeface(Typeface.DEFAULT);

        getRowText(canvas);

        //画 drawable
        drawFlag(canvas, paint, rightFlags);
        setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec));
    }

    private int measureLong(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if ((specMode == MeasureSpec.EXACTLY)) {
            result = specSize;
        } else {
            result = getPaddingLeft() + getPaddingRight() + 100;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    private int measureShort(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = (int) textSize * rowNum + (int) lineSpacing * rowNum + getPaddingTop() + getPaddingBottom();
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
//        Log.e("Tag", "measureShort" + result);
        return result;
    }

    private void drawFlag(Canvas canvas, Paint paint, List<FlagBean> flags) {
        //draw left
        if (flags.size() > 0) {
            for (int i = 0; i < flags.size(); i++) {
                FlagBean flagBean = flags.get(i);
                if (flagBean.getType() == DRAWABLE_FLAG) {
                    if (flagBean.getPadding() == null) flagBean.setPadding(flagPadding);
                    paint.setColor(flagBean.getTextColor() == null ? flagTextColor : flagBean.getTextColor());
                    paint.setTextSize(flagBean.getTextSize() == null ? flagTextSize : flagBean.getTextSize());

                    Paint.FontMetrics a = paint.getFontMetrics();
                    float descent = a.descent;
                    float flagWidth = (int) paint.measureText(flagBean.getTxt());
                    //画flag背景
                    if (flagBean.getRes() != 0) {
                        Bitmap bitmap = getBitmap(DRAWABLE_FLAG, flagBean.getRes(), flagWidth);
                        canvas.drawBitmap(bitmap, getPaddingLeft() + leftTotalWidth,
                                textSize / 2 + getPaddingTop() - bitmap.getHeight() / 2, paint);
                    }

                    //画文字
                    canvas.drawText(flagBean.getTxt(), getPaddingLeft() + leftTotalWidth + flagBean.getPadding(),
                            textSize / 2 + getPaddingTop() + (paint.getTextSize() - descent) / 2, paint);

                    leftTotalWidth += flagWidth + flagPadding * 2 + flagMargin;
//                    Log.e("Tag", "++" + leftTotalWidth + "+" + flagWidth + "+" + flagPadding + "+" + flagMargin);

                } else if (flagBean.getType() == DRAWABLE_PICTURE) {
                    if (flagBean.getBitmap() != null) {
                        Bitmap bitmap = flagBean.getBitmap();
                        if (flagBean.getGravity() == Gravity.LEFT) {
                            canvas.drawBitmap(bitmap, getPaddingLeft() + leftTotalWidth,
                                    textSize / 2 + getPaddingTop() - bitmap.getHeight() / 2, paint);

                            leftTotalWidth += bitmap.getWidth() + flagMargin;
                        } else if (flagBean.getGravity() == Gravity.RIGHT) {
                            if (i == 0) {
                                leftTotalWidth += textMarginRight;
                            }
                            if (leftTotalWidth + bitmap.getWidth() + getPaddingLeft() + getPaddingRight() > getWidth()) {
                                leftTotalWidth = 0;
                                rowNum++;
                            }
                            canvas.drawBitmap(bitmap, getPaddingLeft() + leftTotalWidth,
                                    textSize / 2 + textSize * (rowNum - 1) + lineSpacing * (rowNum - 1) +
                                            getPaddingTop() - bitmap.getHeight() / 2, paint);
                            leftTotalWidth += bitmap.getWidth() + flagMargin;
                        }
                        bitmap.recycle();
                    }
                }
            }
        }
    }


    private void getRowText(Canvas canvas) {
        Paint.FontMetrics a = paint.getFontMetrics();
        float descent = a.descent;
        if (TextUtils.isEmpty(contentString)) {
            return;
        }
        for (int i = 0; i <= contentString.length(); i++) {
            float parentWidth = getWidth() - getPaddingLeft() - getPaddingRight();
            if (rowNum == 1) {
//                Log.e("Tag", getPaddingLeft() + "---" + getPaddingRight() + "---" + leftTotalWidth + "---" + textMarginLeft);
                parentWidth = getWidth() - (getPaddingLeft() + getPaddingRight() + leftTotalWidth + textMarginLeft);
            }
            if (parentWidth < 0) {
                return;
            }

            int ddd = 0;
            if (maxLine == rowNum) {
//                Log.e("Tag", "xxxxx" + drawableTotalWidth);
                ddd = drawableTotalWidth;
            }
            float addOneWidth = (int) paint.measureText(contentString.substring(index, i));

            if (addOneWidth > (parentWidth - ddd)) {

                String substring = contentString.substring(index, i - 1);
                if (maxLine > 0 && maxLine == rowNum && substring.length() > 2) {
//                    Log.e("Tag", "zzz" + substring);
                    substring = substring.substring(0, substring.length() - 2) + "...";

                }
                if (rowNum == 1) {
                    canvas.drawText(substring, getPaddingLeft() + leftTotalWidth + textMarginLeft,
                            textSize / 2 + getPaddingTop() + (paint.getTextSize() - descent) / 2, paint);
                } else {
                    canvas.drawText(substring, getPaddingLeft(),
                            textSize / 2 + getPaddingTop() + textSize * (rowNum - 1) + lineSpacing * (rowNum - 1) + (paint.getTextSize() - descent) / 2, paint);
                }

                if (maxLine == rowNum) {
                    leftTotalWidth += (int) paint.measureText(substring);
                    return;
                }

                index += substring.length();
                rowNum++;

            }
            //最后一行
            if (i == contentString.length()) {
                String substring = contentString.substring(index, contentString.length());

                if (rowNum == 1) {
                    leftTotalWidth += textMarginLeft;
                } else {
                    leftTotalWidth = 0;
                }
                canvas.drawText(substring, getPaddingLeft() + leftTotalWidth,
                        textSize / 2 + getPaddingTop() + textSize * (rowNum - 1) + lineSpacing * (rowNum - 1) + (paint.getTextSize() - descent) / 2, paint);
                if (rowNum == 1) {
                    leftTotalWidth += paint.measureText(substring);
                } else {
                    leftTotalWidth = paint.measureText(substring);
                }
            }
//            }
        }
    }

    private Bitmap convertViewToBitmap(View view) {
        view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        return bitmap;
    }

    private Bitmap getBitmap(int drawableType, int vectorDrawableId, float flagWidth) {
        Bitmap bitmap = null;
        int width = 0;
        int height = 0;
//        if (Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP){
        Drawable vectorDrawable = getContext().getResources().getDrawable(vectorDrawableId);
        if (drawableType == DRAWABLE_FLAG) {
            width = (int) (flagWidth + flagPadding * 2);
            height = (int) textSize;
        } else if (drawableType == DRAWABLE_PICTURE) {
            width = vectorDrawable.getIntrinsicWidth();
            height = vectorDrawable.getIntrinsicHeight();
        }
        bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
        Canvas canvas = new Canvas(bitmap);
        vectorDrawable.setBounds(0, 0, width, height);
        vectorDrawable.draw(canvas);
//        }else {
//            bitmap = BitmapFactory.decodeResource(context.getResources(), vectorDrawableId);
//        }
        return bitmap;
    }

    public void setMaxLine(int maxLine) {
        this.maxLine = maxLine;
    }

    class FlagBean {

        private int type;// 1 flag 2 drawable
        private int gravity;//只识别左右

        private String txt;
        private int Res;
        private Drawable drawable;
        private Bitmap bitmap;
        private Float padding;
        private Integer textColor;
        private Float textSize;

        public Float getTextSize() {
            return textSize;
        }

        public void setTextSize(Float textSize) {
            this.textSize = textSize;
        }

        public Integer getTextColor() {
            return textColor;
        }

        public void setTextColor(Integer textColor) {
            this.textColor = textColor;
        }

        public Float getPadding() {
            return padding;
        }

        public void setPadding(Float padding) {
            this.padding = padding;
        }

        public int getGravity() {
            return gravity;
        }

        public void setGravity(int gravity) {
            this.gravity = gravity;
        }

        public String getTxt() {
            return txt;
        }

        public void setTxt(String txt) {
            this.txt = txt;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

        public int getRes() {
            return Res;
        }

        public void setRes(int res) {
            Res = res;
        }

        public Drawable getDrawable() {
            return drawable;
        }

        public void setDrawable(Drawable drawable) {
            this.drawable = drawable;
        }

        public Bitmap getBitmap() {
            return bitmap;
        }

        public void setBitmap(Bitmap bitmap) {
            this.bitmap = bitmap;
        }
    }
}
